package com.lds.config.center.server.business.cluster.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lds.config.center.common.model.cluster.request.ClusterBaseBatchCreateRequest;
import com.lds.config.center.common.model.cluster.request.ClusterBaseBatchDeleteRequest;
import com.lds.config.center.common.model.cluster.request.ClusterBaseBatchUpdateRequest;
import com.lds.config.center.common.model.cluster.request.ClusterBaseCreateRequest;
import com.lds.config.center.common.model.cluster.request.ClusterBaseDeleteRequest;
import com.lds.config.center.common.model.cluster.request.ClusterBaseGetByIdRequest;
import com.lds.config.center.common.model.cluster.request.ClusterBaseGetByIdsRequest;
import com.lds.config.center.common.model.cluster.request.ClusterBaseGetByKeyRequest;
import com.lds.config.center.common.model.cluster.request.ClusterBaseListPageRequest;
import com.lds.config.center.common.model.cluster.request.ClusterBaseListRequest;
import com.lds.config.center.common.model.cluster.request.ClusterBaseUpdateRequest;
import com.lds.config.center.common.model.cluster.response.ClusterBaseBatchCreateResponse;
import com.lds.config.center.common.model.cluster.response.ClusterBaseBatchDeleteResponse;
import com.lds.config.center.common.model.cluster.response.ClusterBaseBatchUpdateResponse;
import com.lds.config.center.common.model.cluster.response.ClusterBaseDeleteResponse;
import com.lds.config.center.common.model.cluster.response.ClusterBaseListResponse;
import com.lds.config.center.common.model.cluster.response.ClusterBaseResponse;
import com.lds.config.center.server.business.app.entity.App;
import com.lds.config.center.server.business.app.mapper.AppMapper;
import com.lds.config.center.server.business.cluster.converter.ClusterBaseCreateRequestToEntityConverter;
import com.lds.config.center.server.business.cluster.converter.ClusterBaseGetByKeyRequestToEntityConverter;
import com.lds.config.center.server.business.cluster.converter.ClusterBaseListPageRequestToEntityConverter;
import com.lds.config.center.server.business.cluster.converter.ClusterBaseListRequestToEntityConverter;
import com.lds.config.center.server.business.cluster.converter.ClusterBaseUpdateRequestToEntityConverter;
import com.lds.config.center.server.business.cluster.converter.ClusterToBaseResponseConverter;
import com.lds.config.center.server.business.cluster.entity.Cluster;
import com.lds.config.center.server.business.cluster.mapper.ClusterMapper;
import com.lds.config.center.server.business.cluster.service.ClusterBaseService;
import com.lds.config.center.server.common.enums.ServerErrorEnum;
import com.lds.management.center.common.model.db.OrderBy;
import com.lds.management.center.common.model.db.PageResult;
import com.lds.management.center.common.model.dto.ResultDTO;
import com.lds.management.center.common.util.AssertUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 基础服务实现类
 *
 * @author lidongsheng
 * @since 2025-06-26
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ClusterBaseServiceImpl implements ClusterBaseService {

    private final ClusterMapper clusterMapper;
    private final AppMapper appMapper;
    private final ClusterBaseCreateRequestToEntityConverter clusterBaseCreateRequestToEntityConverter;
    private final ClusterBaseUpdateRequestToEntityConverter clusterBaseUpdateRequestToEntityConverter;
    private final ClusterBaseListRequestToEntityConverter clusterBaseListRequestToEntityConverter;
    private final ClusterToBaseResponseConverter clusterToBaseResponseConverter;
    private final ClusterBaseListPageRequestToEntityConverter clusterBaseListPageRequestToEntityConverter;
    private final ClusterBaseGetByKeyRequestToEntityConverter clusterBaseGetByKeyRequestToEntityConverter;

    @Override
    @Transactional
    public ResultDTO<ClusterBaseResponse> createCluster(ClusterBaseCreateRequest request) {
        try {
            Cluster cluster = clusterBaseCreateRequestToEntityConverter.convert(request);
            clusterMapper.insert(cluster);
            ClusterBaseResponse response = clusterToBaseResponseConverter.convert(cluster);
            return ResultDTO.success(response);
        } catch (DuplicateKeyException e) {
            return ResultDTO.fail("DATA_REPEAT", "数据重复");
        }
    }

    @Transactional
    @Override
    public ResultDTO<ClusterBaseBatchCreateResponse> batchCreateCluster(ClusterBaseBatchCreateRequest request) {
        ClusterBaseBatchCreateResponse response = ClusterBaseBatchCreateResponse.builder()
                .responses(request.getRequests().stream().map(this::createCluster).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    @Transactional
    @Override
    public ResultDTO<ClusterBaseDeleteResponse> deleteCluster(ClusterBaseDeleteRequest request) {
        // app引用关系
        Long appCount = appMapper.selectCount(new QueryWrapper<>(App.builder().clusterId(request.getId()).build()));
        AssertUtil.assertTrue(appCount == 0, ServerErrorEnum.APP_USING);


        clusterMapper.deleteById(request.getId());

        ClusterBaseDeleteResponse response = ClusterBaseDeleteResponse.builder().request(request).build();
        return ResultDTO.success(response);
    }

    @Transactional
    @Override
    public ResultDTO<ClusterBaseBatchDeleteResponse> batchDeleteCluster(ClusterBaseBatchDeleteRequest request) {
        ClusterBaseBatchDeleteResponse response = ClusterBaseBatchDeleteResponse.builder()
                .responses(request.getRequests().stream().map(this::deleteCluster).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    @Transactional
    @Override
    public ResultDTO<ClusterBaseResponse> updateCluster(ClusterBaseUpdateRequest request) {
        try {
            Cluster cluster = clusterBaseUpdateRequestToEntityConverter.convert(request);
            clusterMapper.updateById(cluster);
            ClusterBaseResponse response = clusterToBaseResponseConverter.convert(cluster);
            return ResultDTO.success(response);
        } catch (DuplicateKeyException e) {
            return ResultDTO.fail("DATA_REPEAT", "数据重复");
        }
    }

    @Transactional
    @Override
    public ResultDTO<ClusterBaseBatchUpdateResponse> batchUpdateCluster(ClusterBaseBatchUpdateRequest request) {
        ClusterBaseBatchUpdateResponse response = ClusterBaseBatchUpdateResponse.builder()
                .requests(request.getRequests().stream().map(this::updateCluster).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<ClusterBaseResponse> getClusterById(ClusterBaseGetByIdRequest request) {
        Cluster cluster = clusterMapper.selectById(request.getId());
        if (cluster == null) {
            return ResultDTO.success();
        }

        ClusterBaseResponse response = clusterToBaseResponseConverter.convert(cluster);
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<ClusterBaseListResponse> getClusterByIds(ClusterBaseGetByIdsRequest request) {
        List<Cluster> list = request.getIds().stream().map(id -> clusterMapper.selectById(id)).collect(Collectors.toList());
        return ResultDTO.success(ClusterBaseListResponse.builder()
                .clusters(list.stream().map(cluster -> clusterToBaseResponseConverter.convert(cluster)).collect(Collectors.toList()))
                .build());
    }

    @Override
    public Cluster getClusterByKey(ClusterBaseGetByKeyRequest request) {
        return clusterMapper.selectOne(new QueryWrapper<>(clusterBaseGetByKeyRequestToEntityConverter.convert(request)));
    }

    @Override
    public ResultDTO<ClusterBaseListResponse> listCluster(ClusterBaseListRequest request) {
        QueryWrapper<Cluster> wrapper = new QueryWrapper<>(clusterBaseListRequestToEntityConverter.convert(request));
        if (StringUtils.isNotEmpty(request.getOrderByKey())) {
            wrapper.orderByDesc(request.getOrderByKey());
        }

        List<Cluster> clusters = clusterMapper.selectList(wrapper);

        ClusterBaseListResponse response = ClusterBaseListResponse.builder()
                .clusters(clusters.stream().map(clusterToBaseResponseConverter::convert).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<ClusterBaseListResponse> listAllCluster(OrderBy orderBy) {
        ClusterBaseListRequest clusterRequest = ClusterBaseListRequest.builder().build();
        clusterRequest.setOrderByKey(orderBy.getOrderByKey());
        return listCluster(clusterRequest);
    }

    @Override
    public ResultDTO<PageResult<ClusterBaseResponse>> listClusterPage(ClusterBaseListPageRequest request) {
        Page<Cluster> page = new Page<>(request.getPageNum(), request.getPageSize(), true);

        QueryWrapper<Cluster> wrapper = new QueryWrapper<>(clusterBaseListPageRequestToEntityConverter.convert(request));
        if (StringUtils.isNotEmpty(request.getOrderByKey())) {
            if (request.getOrderByDesc() != null && !request.getOrderByDesc()) {
                wrapper.orderByAsc(request.getOrderByKey());
            } else {
                wrapper.orderByDesc(request.getOrderByKey());
            }
        }

        IPage<Cluster> pageResult = clusterMapper.selectPage(page, wrapper);

        PageResult<ClusterBaseResponse> response = new PageResult<>(
                pageResult.getTotal(), pageResult.getPages(), pageResult.getCurrent(), pageResult.getSize(),
                pageResult.getRecords().stream().map(clusterToBaseResponseConverter::convert).collect(Collectors.toList()));
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<ClusterBaseBatchCreateResponse> batchCreateClusterAsync(ClusterBaseBatchCreateRequest request) {
        ClusterBaseBatchCreateResponse response = ClusterBaseBatchCreateResponse.builder()
                .responses(request.getRequests().parallelStream().map(this::createCluster).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<ClusterBaseBatchDeleteResponse> batchDeleteClusterAsync(ClusterBaseBatchDeleteRequest request) {
        ClusterBaseBatchDeleteResponse response = ClusterBaseBatchDeleteResponse.builder()
                .responses(request.getRequests().parallelStream().map(this::deleteCluster).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<ClusterBaseBatchUpdateResponse> batchUpdateClusterAsync(ClusterBaseBatchUpdateRequest request) {
        ClusterBaseBatchUpdateResponse response = ClusterBaseBatchUpdateResponse.builder()
                .requests(request.getRequests().parallelStream().map(this::updateCluster).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

}
